﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Collections;
using System.Xml;
//using System.Data.Common;
using UnityEngine;
using NL.Web;

namespace Galaxy
{
    public class ParamPoolData
    {
        public byte[] mBuffer;
        public ParamPoolData()
        {

        }
        public void InitBuffer(int size)
        {
            mBuffer = new byte[size];
        }

        public void InitParamPool(ParamPool pool)
        {
            if (pool == null || mBuffer == null)
                return;
            int size = pool.mParamBuffer.Length;
            if(size > mBuffer.Length)
                size = mBuffer.Length;
            Buffer.BlockCopy(mBuffer, 0, pool.mParamBuffer, 0, size);
        }

        void InitFromParamPool(ParamPool pool)
        {
            if (pool == null)
                return;
            int size = pool.mParamBuffer.Length;
            if (size > mBuffer.Length)
                size = mBuffer.Length;
            Buffer.BlockCopy(pool.mParamBuffer, 0, mBuffer, 0, size);
        }
    }

    public class ParamPoolDataLoader
    {
        public readonly static ParamPoolDataLoader Instance = new ParamPoolDataLoader();       
       
        public void Load(ParamPoolDefine def)
        {
            if (def == null)
                return;
            string path = "Info/param_" + def.ParamName;
            HTTP.Request<string>(path, null).Wait((w, str) =>
            {
                LoadFromFile(def, str);
            });

            return;
        }
        
        public void LoadFromFile(ParamPoolDefine def, string strVal)
        {
            string[] vallist = strVal.Split("\t");
            string[] valname = vallist[0].Split("\t");
            string[] valtype = vallist[1].Split("\t");
            GalaxyBaseType[] typs = new GalaxyBaseType[valtype.Length];
            int pos = 0;
            foreach(string str in valtype)
            {
                typs[pos] = GalaxyTypeConvert.String2Type(str);
                pos ++;
            }
            int id = 0;
            for(int i=2;i< vallist.Length; ++i)
            {
                string[] tmpVal = vallist[i].Split("\t");

                ParamPoolData data = new ParamPoolData();
                data.InitBuffer(def.PoolSize);
                
                for (int a = 0; a < valname.Length; ++i)
                {
                    string name = valname[i];
                    if(name == "id")
                    {
                        id = Convert.ToInt32(tmpVal[i]);
                        continue;
                    }
                    ParamBase param = def.GetParam(name);
                    if (param == null)
                    {
                        continue;
                    }

                    switch (typs[i])
                    {
                        case GalaxyBaseType.Int8:
                            {
                                sbyte val = Convert.ToSByte(tmpVal[i]);
                                param.SetSByte(ref data.mBuffer, val);
                            }
                            break;
                        case GalaxyBaseType.Int16:
                            {
                                short val = Convert.ToInt16(tmpVal[i]);
                                param.SetInt16(ref data.mBuffer, val);
                            }
                            break;
                        case GalaxyBaseType.Int32:
                            {
                                int val = Convert.ToInt32(tmpVal[i]);
                                param.SetInt32(ref data.mBuffer, val);
                            }
                            break;
                        case GalaxyBaseType.UInt8:
                            {
                                byte val = Convert.ToByte(tmpVal[i]);
                                param.SetByte(ref data.mBuffer, val);
                            }
                            break;
                        case GalaxyBaseType.UInt16:
                            {
                                ushort val = Convert.ToUInt16(tmpVal[i]);
                                param.SetUInt16(ref data.mBuffer, val);
                            }
                            break;
                        case GalaxyBaseType.UInt32:
                            {
                                uint val = Convert.ToUInt32(tmpVal[i]);
                                param.SetUInt32(ref data.mBuffer, val);
                            }
                            break;
                        case GalaxyBaseType.Int64:
                            {
                                long val = Convert.ToInt64(tmpVal[i]);
                                param.SetInt64(ref data.mBuffer, val);
                            }
                            break;
                        case GalaxyBaseType.UInt64:
                            {
                                ulong val = Convert.ToUInt64(tmpVal[i]);
                                param.SetUInt64(ref data.mBuffer, val);
                            }
                            break;
                        case GalaxyBaseType.F32:
                            {
                                float val = Convert.ToSingle(tmpVal[i]);
                                param.SetFloat(ref data.mBuffer, val);
                            }
                            break;
                        case GalaxyBaseType.F64:
                            {
                                double val = Convert.ToDouble(tmpVal[i]);
                                param.SetDouble(ref data.mBuffer, val);
                            }
                            break;
                        case GalaxyBaseType.String:
                            {
                                param.SetString(ref data.mBuffer, tmpVal[i]);
                            }
                            break;
                        case GalaxyBaseType.Bool: break;
                    }
                }

                def.mParamDataMap[id] = data;
            }


         
        }


    }


    public class ParamPoolDefine
    {
        //global function       
        protected static Dictionary<int, ParamPoolDefine> mDefineMap = new Dictionary<int, ParamPoolDefine>();
        public static ParamPoolDefine GetDefine(int ParamID)
        {
            if (!mDefineMap.ContainsKey(ParamID))
                return null;
            return mDefineMap[ParamID];
        }

        public static Dictionary<int, ParamPoolDefine>.ValueCollection GetValues()
        {
            return mDefineMap.Values;
        }
        public static bool AddDefine(ParamPoolDefine define)
        {
            if (define == null)
                return false;
            if (mDefineMap.ContainsKey(define.ParamID))
                return false;
            mDefineMap[define.ParamID] = define;
            return true;
        }
        public static ParamPool CreateParamPool(int ParamType)
        {
            int paramId = ParamPool.GetParamType(ParamType);
            int paramData = ParamPool.GetParamDataID(ParamType);
            return CreateParamPool(paramId, paramData);
        }
        public static ParamPool CreateParamPool(int ParamID, int DataId)
        {
            ParamPoolDefine def = GetDefine(ParamID);
            if (def == null)
                return null;
            ParamPool res = new ParamPool();
            res.Init(def, DataId);
            res.ParamID = ParamID;
            res.DataID = DataId;
            return res;
        }

        public static void ClearDefine()
        {
            if (mDefineMap != null)
            {
                mDefineMap.Clear();
            }
        }

        // instance function
        protected Dictionary<int, ParamBase> mParamMapId;
        protected Dictionary<string, ParamBase> mParamMapName;

        public bool IsLoadData { get; set; }
        public int ParamID { get; set; }
        public int PoolSize { get; set; }
        public string ParamName { get; set; }

        public ParamPoolDefine()
        {
            ParamID = -1;
            PoolSize = 0;
            IsLoadData = false;
            mParamMapId = new Dictionary<int, ParamBase>();
            mParamMapName = new Dictionary<string, ParamBase>();
            mParamDataMap = new Dictionary<int, ParamPoolData>();
        }
        public ParamBase GetParam(int idx)
        {
            ParamBase param;
            if (mParamMapId.TryGetValue(idx, out param))
            {
                return param;
            }
            return null;
        }
        public ParamBase GetParam(string name)
        {
            ParamBase param;
            if (mParamMapName.TryGetValue(name, out param))
            {
                return param;
            }
            return null;
        }
        public bool AddParam(ParamBase param)
        {
            if (param == null)
                return false;
            if (param.mSize <= 0)
                return false;
            if (mParamMapName.ContainsKey(param.mParamName))
                return false;
            if (mParamMapId.ContainsKey(param.mIndex))
                return false;
            mParamMapName[param.mParamName] = param;
            mParamMapId[param.mIndex] = param;
            PoolSize += param.mSize;
            return true;
        }

        public  void ClearParamData()
        {
            if (mParamDataMap != null)
            {
                this.mParamDataMap.Clear();
            }

            if (mParamMapId != null)
            {
                this.mParamMapId.Clear();
            }

            if (mParamMapId != null)
            {
                this.mParamMapName.Clear();
            }
        }

        public Dictionary<int, ParamPoolData> mParamDataMap;
        public void AddData(int id, ParamPoolData data)
        {
            if (mParamDataMap.ContainsKey(id))
                return;
            mParamDataMap[id] = data;
        }

        public ParamPoolData GetData(int id)
        {
            if (mParamDataMap.Count == 0)
            {
               ParamPoolDataLoader.Instance.Load(this);
            }
            if (!mParamDataMap.ContainsKey(id))
            {
                return null;
            }                
            return mParamDataMap[id];
        }
        public bool InitData(ParamPool pool, int dataID)
        {
            if (pool == null)
                return false;
            if (mParamDataMap.Count == 0)
            {
                ParamPoolDataLoader.Instance.Load(this);
            }
            if (mParamDataMap.ContainsKey(dataID))
            {
                ParamPoolData data1 = mParamDataMap[dataID];
                data1.InitParamPool(pool);
            }
            return true;
        }
    }

    public class ParamNameKey
    {
        public string Name;
        public ParamBase ParamBase;

        public ParamNameKey(string name)
        {
            Name = name;
            ParamBase = null;
        }
    }

    public class ParamIdKey
    {
        public int Id;
        public ParamBase ParamBase;

        public ParamIdKey(int id)
        {
            Id = id;
            ParamBase = null;
        }
    }

    public class ParamPool
    {
        public delegate void HandleParamChange(string name, ParamPool pool, object oldVal, object newVal);
        public int ParamTypeID;
        public int ParamID;
        public int DataID;

        public HandleParamChange ParamChangeHandle;
        public ParamPoolDefine mParamDefine;

        public byte[] mParamBuffer;

        protected const int MAX_PARAM_COUNT_IN_BLOCK = 32;

        public static int GetParamTypeID(int paramid, int dataid)
        {
            int param = (int)paramid;
            return (int)((param << 24) + (dataid & 0x00ffffff));
        }
        public static int GetParamType(int paramTypeID)
        {
            int res = ((int)paramTypeID >> 24);
            if (res<0)
            {
                return -1;
            }
            return res;
        }
        public static int GetParamDataID(int paramTypeID)
        {
            return (paramTypeID & 0x00ffffff);
        }

        //为了给Lua调用无GC的方法
        public static int GetParamDataIndex(string name)
        {
            if (string.IsNullOrEmpty(name))
                return -1;
            if (!name.StartsWith("data"))
                return -1;

            string strColumn = name.Substring(4);
            int nColumn = System.Convert.ToInt32(strColumn);
            return nColumn;
        }
        public void Init(ParamPoolDefine define, int dataID = 0)
        {
            mParamDefine = define;
            mParamBuffer = new byte[define.PoolSize];
            if(define != null)
            {
                define.InitData(this, dataID);
            }
        }

        public ParamBase GetParam(int idx)
        {
            if (mParamDefine == null)
                return null;
            return mParamDefine.GetParam(idx);
        }
        public ParamBase GetParam(string name)
        {
            if (mParamDefine == null)
                return null;
            return mParamDefine.GetParam(name);
        }

        /// <summary>
        /// get function by ParamPoolKey
        /// </summary>
        public sbyte GetSByte(ParamNameKey key, sbyte def = 0)
        {
            if (key.ParamBase == null)
            {
                key.ParamBase = GetParam(key.Name);
                if (key.ParamBase == null)
                {
                    return def;
                }
            }
            return key.ParamBase.GetSByte(ref mParamBuffer);
        }
        public sbyte GetSByte(ParamIdKey key, sbyte def = 0)
        {
            if (key.ParamBase == null)
            {
                key.ParamBase = GetParam(key.Id);
                if (key.ParamBase == null)
                {
                    return def;
                }
            }
            return key.ParamBase.GetSByte(ref mParamBuffer);
        }
        public byte GetByte(ParamNameKey key, byte def = 0)
        {
            if (key.ParamBase == null)
            {
                key.ParamBase = GetParam(key.Name);
                if (key.ParamBase == null)
                {
                    return def;
                }
            }
            return key.ParamBase.GetByte(ref mParamBuffer);
        }
        public byte GetByte(ParamIdKey key, byte def = 0)
        {
            if (key.ParamBase == null)
            {
                key.ParamBase = GetParam(key.Id);
                if (key.ParamBase == null)
                {
                    return def;
                }
            }
            return key.ParamBase.GetByte(ref mParamBuffer);
        }
        public short GetInt16(ParamNameKey key, short def = 0)
        {
            if (key.ParamBase == null)
            {
                key.ParamBase = GetParam(key.Name);
                if (key.ParamBase == null)
                {
                    return def;
                }
            }
            return key.ParamBase.GetInt16(ref mParamBuffer);
        }
        public short GetInt16(ParamIdKey key, short def = 0)
        {
            if (key.ParamBase == null)
            {
                key.ParamBase = GetParam(key.Id);
                if (key.ParamBase == null)
                {
                    return def;
                }
            }
            return key.ParamBase.GetInt16(ref mParamBuffer);
        }
        public ushort GetUInt16(ParamNameKey key, ushort def = 0)
        {
            if (key.ParamBase == null)
            {
                key.ParamBase = GetParam(key.Name);
                if (key.ParamBase == null)
                {
                    return def;
                }
            }
            return key.ParamBase.GetUInt16(ref mParamBuffer);
        }
        public ushort GetUInt16(ParamIdKey key, ushort def = 0)
        {
            if (key.ParamBase == null)
            {
                key.ParamBase = GetParam(key.Id);
                if (key.ParamBase == null)
                {
                    return def;
                }

            }
            return key.ParamBase.GetUInt16(ref mParamBuffer);
        }
        public int GetInt32(ParamNameKey key, int def = 0)
        {
            if (key.ParamBase == null)
            {
                key.ParamBase = GetParam(key.Name);
                if (key.ParamBase == null)
                {
                    return def;
                }
            }
            return key.ParamBase.GetInt32(ref mParamBuffer);
        }
        public int GetInt32(ParamIdKey key, int def = 0)
        {
            if (key.ParamBase == null)
            {
                key.ParamBase = GetParam(key.Id);
                if (key.ParamBase == null)
                {
                    return def;
                }

            }
            return key.ParamBase.GetInt32(ref mParamBuffer);
        }
        public uint GetUInt32(ParamNameKey key, uint def = 0)
        {
            if (key.ParamBase == null)
            {
                key.ParamBase = GetParam(key.Name);
                if (key.ParamBase == null)
                {
                    return def;
                }
            }
            return key.ParamBase.GetUInt32(ref mParamBuffer);
        }
        public uint GetUInt32(ParamIdKey key, uint def = 0)
        {
            if (key.ParamBase == null)
            {
                key.ParamBase = GetParam(key.Id);
                if (key.ParamBase == null)
                {
                    return def;
                }
            }
            return key.ParamBase.GetUInt32(ref mParamBuffer);
        }
        public long GetInt64(ParamNameKey key, long def = 0)
        {
            if (key.ParamBase == null)
            {
                key.ParamBase = GetParam(key.Name);
                if (key.ParamBase == null)
                {
                    return def;
                }
            }
            return key.ParamBase.GetInt64(ref mParamBuffer);
        }
        public long GetInt64(ParamIdKey key, long def = 0)
        {
            if (key.ParamBase == null)
            {
                key.ParamBase = GetParam(key.Id);
                if (key.ParamBase == null)
                {
                    return def;
                }
            }
            return key.ParamBase.GetInt64(ref mParamBuffer);
        }
        public ulong GetUInt64(ParamNameKey key, ulong def = 0)
        {
            if (key.ParamBase == null)
            {
                key.ParamBase = GetParam(key.Name);
                if (key.ParamBase == null)
                {
                    return def;
                }
            }
            return key.ParamBase.GetUInt64(ref mParamBuffer);
        }
        public ulong GetUInt64(ParamIdKey key, ulong def = 0)
        {
            if (key.ParamBase == null)
            {
                key.ParamBase = GetParam(key.Id);
                if (key.ParamBase == null)
                {
                    return def;
                }
            }
            return key.ParamBase.GetUInt64(ref mParamBuffer);
        }

        public float GetFloat(ParamNameKey key, float def = 0)
        {
            if (key.ParamBase == null)
            {
                key.ParamBase = GetParam(key.Name);
                if (key.ParamBase == null)
                {
                    return def;
                }
            }
            return key.ParamBase.GetFloat(ref mParamBuffer);
        }
        public float GetFloat(ParamIdKey key, float def = 0)
        {
            if (key.ParamBase == null)
            {
                key.ParamBase = GetParam(key.Id);
                if (key.ParamBase == null)
                {
                    return def;
                }
            }
            return key.ParamBase.GetFloat(ref mParamBuffer);
        }

        public double GetDouble(ParamNameKey key, double def = 0)
        {
            if (key.ParamBase == null)
            {
                key.ParamBase = GetParam(key.Name);
                if (key.ParamBase == null)
                {
                    return def;
                }
            }
            return key.ParamBase.GetDouble(ref mParamBuffer);
        }
        public double GetDouble(ParamIdKey key, double def = 0)
        {
            if (key.ParamBase == null)
            {
                key.ParamBase = GetParam(key.Id);
                if (key.ParamBase == null)
                {
                    return def;
                }
            }
            return key.ParamBase.GetDouble(ref mParamBuffer);
        }

        public string GetString(ParamNameKey key)
        {
            if (key.ParamBase == null)
            {
                key.ParamBase = GetParam(key.Name);
                if (key.ParamBase == null)
                {
                    return string.Empty;
                }
            }
            return key.ParamBase.GetString(ref mParamBuffer);
        }
        public string GetString_UTF8(ParamNameKey key)
        {
            if (key.ParamBase == null)
            {
                key.ParamBase = GetParam(key.Name);
                if (key.ParamBase == null)
                {
                    return string.Empty;
                }
            }
            return key.ParamBase.GetString_UTF8(ref mParamBuffer);
        }
        public string GetString(ParamIdKey key)
        {
            if (key.ParamBase == null)
            {
                key.ParamBase = GetParam(key.Id);
                if (key.ParamBase == null)
                {
                    return string.Empty;
                }
            }
            return key.ParamBase.GetString(ref mParamBuffer);
        }

        public string GetString_UTF8(ParamIdKey key)
        {
            if (key.ParamBase == null)
            {
                key.ParamBase = GetParam(key.Id);
                if (key.ParamBase == null)
                {
                    return string.Empty;
                }
            }
            return key.ParamBase.GetString_UTF8(ref mParamBuffer);
        }

        public bool GetBool(ParamNameKey key, bool def = false)
        {
            if (key.ParamBase == null)
            {
                key.ParamBase = GetParam(key.Name);
                if (key.ParamBase == null)
                {
                    return def;
                }
            }
            return key.ParamBase.GetBool(ref mParamBuffer);
        }
        public bool GetBool(ParamIdKey key, bool def = false)
        {
            if (key.ParamBase == null)
            {
                key.ParamBase = GetParam(key.Id);
                if (key.ParamBase == null)
                {
                    return def;
                }
            }
            return key.ParamBase.GetBool(ref mParamBuffer);
        }

        public object GetValue(ParamNameKey key)
        {
            if (key.ParamBase == null)
            {
                key.ParamBase = GetParam(key.Name);
                if (key.ParamBase == null)
                {
                    return null;
                }
            }
            return key.ParamBase.GetValue(ref mParamBuffer);
        }
        public object GetValue(ParamIdKey key)
        {
            if (key.ParamBase == null)
            {
                key.ParamBase = GetParam(key.Id);
                if (key.ParamBase == null)
                {
                    return null;
                }
            }
            return key.ParamBase.GetValue(ref mParamBuffer);
        }

        /// <summary>
        /// get function by name
        /// </summary>
        public sbyte GetSByte(string name, sbyte def = 0)
        {
            ParamBase param = GetParam(name);
            if(param == null)
            {
                return def;
            }
            return param.GetSByte(ref mParamBuffer);
        }
        public sbyte GetSByte(int idx, sbyte def = 0)
        {
            ParamBase param = GetParam(idx);
            if (param == null)
            {
                return def;
            }
            return param.GetSByte(ref mParamBuffer);
        }
        public byte GetByte(string name, byte def = 0)
        {
            ParamBase param = GetParam(name);
            if (param == null)
            {
                return def;
            }
            return param.GetByte(ref mParamBuffer);
        }
        public byte GetByte(int idx, byte def = 0)
        {
            ParamBase param = GetParam(idx);
            if (param == null)
            {
                return def;
            }
            return param.GetByte(ref mParamBuffer);
        }
        public short GetInt16(string name, short def = 0)
        {
            ParamBase param = GetParam(name);
            if (param == null)
            {
                return def;
            }
            return param.GetInt16(ref mParamBuffer);
        }
        public short GetInt16(int idx, short def = 0)
        {
            ParamBase param = GetParam(idx);
            if (param == null)
            {
                return def;
            }
            return param.GetInt16(ref mParamBuffer);
        }
        public ushort GetUInt16(string name, ushort def = 0)
        {
            ParamBase param = GetParam(name);
            if (param == null)
            {
                return def;
            }
            return param.GetUInt16(ref mParamBuffer);
        }
        public ushort GetUInt16(int idx, ushort def = 0)
        {
            ParamBase param = GetParam(idx);
            if (param == null)
            {
                return def;
            }
            return param.GetUInt16(ref mParamBuffer);
        }
        public int GetInt32(string name, int def = 0)
        {
            ParamBase param = GetParam(name);
            if (param == null)
            {
                return def;
            }
            return param.GetInt32(ref mParamBuffer);
        }
        public int GetInt32(int idx, int def = 0)
        {
            ParamBase param = GetParam(idx);
            if (param == null)
            {
                return def;
            }
            return param.GetInt32(ref mParamBuffer);
        }
        public uint GetUInt32(string name, uint def = 0)
        {
            ParamBase param = GetParam(name);
            if (param == null)
            {
                return def;
            }
            return param.GetUInt32(ref mParamBuffer);
        }
        public uint GetUInt32(int idx, uint def = 0)
        {
            ParamBase param = GetParam(idx);
            if (param == null)
            {
                return def;
            }
            return param.GetUInt32(ref mParamBuffer);
        }
        public long GetInt64(string name, long def = 0)
        {
            ParamBase param = GetParam(name);
            if (param == null)
            {
                return def;
            }
            return param.GetInt64(ref mParamBuffer);
        }
        public long GetInt64(int idx, long def = 0)
        {
            ParamBase param = GetParam(idx);
            if (param == null)
            {
                return def;
            }
            return param.GetInt64(ref mParamBuffer);
        }
        public ulong GetUInt64(string name, ulong def = 0)
        {
            ParamBase param = GetParam(name);
            if (param == null)
            {
                return def;
            }
            return param.GetUInt64(ref mParamBuffer);
        }
        public ulong GetUInt64(int idx, ulong def = 0)
        {
            ParamBase param = GetParam(idx);
            if (param == null)
            {
                return def;
            }
            return param.GetUInt64(ref mParamBuffer);
        }

        public float GetFloat(string name, float def = 0)
        {
            ParamBase param = GetParam(name);
            if (param == null)
            {
                return def;
            }
            return param.GetFloat(ref mParamBuffer);
        }
        public float GetFloat(int idx, float def = 0)
        {
            ParamBase param = GetParam(idx);
            if (param == null)
            {
                return def;
            }
            return param.GetFloat(ref mParamBuffer);
        }

        public double GetDouble(string name, double def = 0)
        {
            ParamBase param = GetParam(name);
            if (param == null)
            {
                return def;
            }
            return param.GetDouble(ref mParamBuffer);
        }
        public double GetDouble(int idx, double def = 0)
        {
            ParamBase param = GetParam(idx);
            if (param == null)
            {
                return def;
            }
            return param.GetDouble(ref mParamBuffer);
        }

        public string GetString(string name)
        {
            ParamBase param = GetParam(name);
            if (param == null)
            {
                return "";
            }
            return param.GetString(ref mParamBuffer);
        }
        public string GetString_UTF8(string name)
        {
            ParamBase param = GetParam(name);
            if (param == null)
            {
                return "";
            }
            return param.GetString_UTF8(ref mParamBuffer);
        }
        public string GetString(int idx)
        {
            ParamBase param = GetParam(idx);
            if (param == null)
            {
                return "";
            }
            return param.GetString(ref mParamBuffer);
        }

        public string GetString_UTF8(int idx)
        {
            ParamBase param = GetParam(idx);
            if (param == null)
            {
                return "";
            }
            return param.GetString_UTF8(ref mParamBuffer);
        }

        public bool GetBool(string name)
        {
            ParamBase param = GetParam(name);
            if (param == null)
            {
                return false;
            }
            return param.GetBool(ref mParamBuffer);
        }
        public bool GetBool(int idx)
        {
            ParamBase param = GetParam(idx);
            if (param == null)
            {
                return false;
            }
            return param.GetBool(ref mParamBuffer);
        }

        public object GetValue(string name)
        {
            ParamBase param = GetParam(name);
            if (param == null)
            {
                return null;
            }
            return param.GetValue(ref mParamBuffer);
        }
        public object GetValue(int idx)
        {
            ParamBase param = GetParam(idx);
            if (param == null)
            {
                return null;
            }
            return param.GetValue(ref mParamBuffer);
        }

        /// <summary>
        /// set function
        /// </summary>
        ///  
        public void SetSByte(string name, sbyte val)
        {
            ParamBase param = GetParam(name);
            if(param == null)
            {
                return;
            }
            object oldVal = param.GetSByte(ref mParamBuffer);
            param.SetSByte(ref mParamBuffer, val);
            if(ParamChangeHandle != null)
                ParamChangeHandle(name, this, oldVal, val);
        }
        public void SetSByte(int idx, sbyte val)
        {
            ParamBase param = GetParam(idx);
            if (param == null)
            {
                return;
            }
            object oldVal = param.GetSByte(ref mParamBuffer);
            param.SetSByte(ref mParamBuffer, val);
            if (ParamChangeHandle != null)
                ParamChangeHandle(param.mParamName, this, oldVal, val);
        }

        public void SetByte(string name, byte val)
        {
            ParamBase param = GetParam(name);
            if (param == null)
            {
                return;
            }
            object oldVal = param.GetByte(ref mParamBuffer);
            param.SetByte(ref mParamBuffer, val);
            if (ParamChangeHandle != null)
                ParamChangeHandle(name, this, oldVal, val);
        }
        public void SetByte(int idx, byte val)
        {
            ParamBase param = GetParam(idx);
            if (param == null)
            {
                return;
            }
            object oldVal = param.GetByte(ref mParamBuffer);
            param.SetByte(ref mParamBuffer, val);
            if (ParamChangeHandle != null)
                ParamChangeHandle(param.mParamName, this, oldVal, val);
        }

        public void SetInt16(string name, short val)
        {
            ParamBase param = GetParam(name);
            if (param == null)
            {
                return;
            }
            object oldVal = param.GetInt16(ref mParamBuffer);
            param.SetInt16(ref mParamBuffer, val);
            if (ParamChangeHandle != null)
                ParamChangeHandle(name, this, oldVal, val);
        }
        public void SetInt16(int idx, short val)
        {
            ParamBase param = GetParam(idx);
            if (param == null)
            {
                return;
            }
            object oldVal = param.GetInt16(ref mParamBuffer);
            param.SetInt16(ref mParamBuffer, val);
            if (ParamChangeHandle != null)
                ParamChangeHandle(param.mParamName, this, oldVal, val);
        }
        public void SetUInt16(string name, ushort val)
        {
            ParamBase param = GetParam(name);
            if (param == null)
            {
                return;
            }
            object oldVal = param.GetUInt16(ref mParamBuffer);
            param.SetUInt16(ref mParamBuffer, val);
            if (ParamChangeHandle != null)
                ParamChangeHandle(name, this, oldVal, val);
        }
        public void SetUInt16(int idx, ushort val)
        {
            ParamBase param = GetParam(idx);
            if (param == null)
            {
                return;
            }
            object oldVal = param.GetUInt16(ref mParamBuffer);
            param.SetUInt16(ref mParamBuffer, val);
            if (ParamChangeHandle != null)
                ParamChangeHandle(param.mParamName, this, oldVal, val);
        }
        public void SetInt32(string name, int val)
        {
            ParamBase param = GetParam(name);
            if (param == null)
            {
                return;
            }
            object oldVal = param.GetInt32(ref mParamBuffer);
            param.SetInt32(ref mParamBuffer, val);
            if (ParamChangeHandle != null)
                ParamChangeHandle(name, this, oldVal, val);
        }
        public void SetInt32(int idx, int val)
        {
            ParamBase param = GetParam(idx);
            if (param == null)
            {
                return;
            }
            object oldVal = param.GetInt32(ref mParamBuffer);
            param.SetInt32(ref mParamBuffer, val);
            if (ParamChangeHandle != null)
                ParamChangeHandle(param.mParamName, this, oldVal, val);
        }
        public void SetUInt32(string name, uint val)
        {
            ParamBase param = GetParam(name);
            if (param == null)
            {
                return;
            }
            object oldVal = param.GetUInt32(ref mParamBuffer);
            param.SetUInt32(ref mParamBuffer, val);
            if (ParamChangeHandle != null)
                ParamChangeHandle(name, this, oldVal, val);
        }
        public void SetUInt32(int idx, uint val)
        {
            ParamBase param = GetParam(idx);
            if (param == null)
            {
                return;
            }
            object oldVal = param.GetUInt32(ref mParamBuffer);
            param.SetUInt32(ref mParamBuffer, val);
            if (ParamChangeHandle != null)
                ParamChangeHandle(param.mParamName, this, oldVal, val);
        }
        public void SetInt64(string name, long val)
        {
            ParamBase param = GetParam(name);
            if (param == null)
            {
                return;
            }
            object oldVal = param.GetInt64(ref mParamBuffer);
            param.SetInt64(ref mParamBuffer, val);
            if (ParamChangeHandle != null)
                ParamChangeHandle(name, this, oldVal, val);
        }
        public void SetInt64(int idx, long val)
        {
            ParamBase param = GetParam(idx);
            if (param == null)
            {
                return;
            }
            object oldVal = param.GetInt64(ref mParamBuffer);
            param.SetInt64(ref mParamBuffer, val);
            if (ParamChangeHandle != null)
                ParamChangeHandle(param.mParamName, this, oldVal, val);
        }
        public void SetUInt64(string name, ulong val)
        {
            ParamBase param = GetParam(name);
            if (param == null)
            {
                return;
            }
            object oldVal = param.GetUInt64(ref mParamBuffer);
            param.SetUInt64(ref mParamBuffer, val);
            if (ParamChangeHandle != null)
                ParamChangeHandle(name, this, oldVal, val);
        }
        public void SetUInt64(int idx, ulong val)
        {
            ParamBase param = GetParam(idx);
            if (param == null)
            {
                return;
            }
            object oldVal = param.GetUInt64(ref mParamBuffer);
            param.SetUInt64(ref mParamBuffer, val);
            if (ParamChangeHandle != null)
                ParamChangeHandle(param.mParamName, this, oldVal, val);
        }

        public void SetFloat(string name, float val)
        {
            ParamBase param = GetParam(name);
            if (param == null)
            {
                return;
            }
            object oldVal = param.GetFloat(ref mParamBuffer);
            param.SetFloat(ref mParamBuffer, val);
            if (ParamChangeHandle != null)
                ParamChangeHandle(name, this, oldVal, val);
        }
        public void SetFloat(int idx, float val)
        {
            ParamBase param = GetParam(idx);
            if (param == null)
            {
                return;
            }
            object oldVal = param.GetFloat(ref mParamBuffer);
            param.SetFloat(ref mParamBuffer, val);
            if (ParamChangeHandle != null)
                ParamChangeHandle(param.mParamName, this, oldVal, val);
        }

        public void SetDouble(string name, double val)
        {
            ParamBase param = GetParam(name);
            if (param == null)
            {
                return;
            }
            object oldVal = param.GetDouble(ref mParamBuffer);
            param.SetDouble(ref mParamBuffer, val);
            if (ParamChangeHandle != null)
                ParamChangeHandle(name, this, oldVal, val);
        }
        public void SetDouble(int idx, double val)
        {
            ParamBase param = GetParam(idx);
            if (param == null)
            {
                return;
            }
            object oldVal = param.GetDouble(ref mParamBuffer);
            param.SetDouble(ref mParamBuffer, val);
            if (ParamChangeHandle != null)
                ParamChangeHandle(param.mParamName, this, oldVal, val);
        }

        public void SetString(string name, string val)
        {
            ParamBase param = GetParam(name);
            if (param == null)
            {
                return;
            }
            object oldVal = param.GetString(ref mParamBuffer);
            param.SetString(ref mParamBuffer, val);
            if (ParamChangeHandle != null)
                ParamChangeHandle(name, this, oldVal, val);
        }
        public void SetString(int idx, string val)
        {
            ParamBase param = GetParam(idx);
            if (param == null)
            {
                return;
            }
            object oldVal = param.GetString(ref mParamBuffer);
            param.SetString(ref mParamBuffer, val);
            if (ParamChangeHandle != null)
                ParamChangeHandle(param.mParamName, this, oldVal, val);
        }
        /// <param name="buffer"></param>

        public void Read(byte[] buffer)
        {
            if (buffer.Length <= 0)
            {
                return;
            }
            int pos = 0;
            uint typeid = GalaxyBitConverter.ToUInt32(buffer, pos);
			pos += 1;
            pos += 4;
			pos += 1;
            byte nCount = buffer[pos];
			pos += 1;

            for (int i = 0; i < nCount; ++i)
            {
                if (pos+4 >= buffer.Length)
                {
                    return;
                }
                uint flag = GalaxyBitConverter.ToUInt32(buffer, pos);
                pos += 4;
                byte bIdx = buffer[pos];
                pos += 1;
                for (int j = 0; j < MAX_PARAM_COUNT_IN_BLOCK; ++j)
                {
                    if ((flag & (0x00000001 << j)) != 0)
                    {
                        int cPos = bIdx * MAX_PARAM_COUNT_IN_BLOCK + j;
                        ParamBase param = GetParam(cPos);
                        if (param == null)
                        {
                            continue;
                        }
                        //pre set value callback
                        object val = param.GetValue(ref mParamBuffer);
                        bool bChange = param.PacketRead(buffer, ref pos, mParamBuffer);
                        if(ParamChangeHandle != null && bChange)
                        {
                            object nval = param.GetValue(ref mParamBuffer);
                            ParamChangeHandle(param.mParamName, this, val, nval);
                        }
                        //post set value callback
                    }
                }
            }
        }



       
    }


    public class ParamDefineLoader
    {

        public void LoadDefine(string sFile)
        {
            HTTP.Request<string>(sFile, null).Wait((w, str) =>
            {
                XmlDocument xDoc = new XmlDocument();
                xDoc.LoadXml(str);

                OnLoadXML(xDoc);
            }
            );
        }

        private void OnLoadXML(XmlDocument xDoc)
        {
            ParamPoolDefine.ClearDefine();

            XmlElement xRoot = (XmlElement)xDoc.SelectSingleNode("ParamDefine");
            if (xRoot == null)
                return;
            XmlNodeList xnl = xRoot.ChildNodes;
            int i = 0;

            Debug.LogWarning("LoadDefine Start");
            for (; i < xnl.Count; ++i)
            {
                ParamPoolDefine pDefine = new ParamPoolDefine();
                XmlElement xDef = (XmlElement)xnl[i];
                pDefine.ParamName = xDef.GetAttribute("Name");
                pDefine.ParamID = Convert.ToInt32(xDef.GetAttribute("ID"));
                XmlNodeList xParamlist = xDef.ChildNodes;
                ReadParam(ref pDefine, xParamlist);
                ParamPoolDefine.AddDefine(pDefine);
            }
        }

        public void ReadParam(ref ParamPoolDefine def, XmlNodeList xnl)
        {
            if (def == null)
                return;

            def.ClearParamData();

            for (int i = 0; i < xnl.Count; ++i)
            {
                ParamBase param = new ParamBase();
                XmlElement xMem = (XmlElement)xnl[i];
                param.mParamName = xMem.GetAttribute("Name");
                param.mParamType = (GalaxyBaseType)Convert.ToInt32(xMem.GetAttribute("Type"));
                param.mSize = Convert.ToInt32(xMem.GetAttribute("Size"));
                param.mIndex = Convert.ToInt32(xMem.GetAttribute("Id"));
                param.mOffset = Convert.ToInt32(xMem.GetAttribute("Offset"));
                def.AddParam(param);
            }
        }

    }
}
